import { Injectable, InjectByName, InjectFactory } from '../../decorators/inject';
import { AFormula } from '../../utils/formula/index';
import { IAllPosition, TAllTypes, IExcelValue, IFunctionCalculate } from '../../utils/formula/types';
import { ITableDatas } from '../../cors/table-datas.interface';
import { ValueEmpty } from './value-empty';
import { ValueError } from './value-error';
import { Cell } from '../../cors/cell';

@Injectable()
export class TableFormula extends AFormula {
  protected funcCalculate: IFunctionCalculate;
  constructor(
    @InjectByName('TableDatas') protected tableDatas: ITableDatas,
    @InjectFactory() protected factory: (args: any) => any
  ) {
    super();
  }
  public getRangeValues(range: TRange): (string | number | boolean)[][] {
    let maxRow = range.rowspan !== -1 ? range.row + range.rowspan - 1 : this.tableDatas.getMaxRow();
    let result: (string | number | boolean)[][] = [];
    for (let row = range.row; row <= maxRow; row++) {
      let rowIntance = this.tableDatas.getRow(row);
      let maxCol = range.colspan !== -1 ? range.col + range.colspan - 1 : rowIntance.getMaxCol();
      const colValues: (string | number | boolean)[] = [];
      for (let col = range.col; col <= maxCol; col++) {
        let cell = rowIntance.cells[col];
        if (cell || cell.value instanceof ValueEmpty || cell.value instanceof ValueError) {
          colValues.push(null);
        } else {
          colValues.push(cell.value.getActualValue().getValue());
        }
      }
      result.push(colValues);
    }
    return result;
  }
  protected getPositionValue(val: IAllPosition): (TAllTypes)[] {
    if(val.type === 'position') {
      let res = this.tableDatas.getCell(val.row, val.col, false);
      return [this.formatCellValue(res)]
    }
    if(val.type === 'rowPosition') {
      let rowIntance = this.tableDatas.getRow(val.value);
      let res: TAllTypes[] = [];
      for(let i = 0; i < rowIntance.getMaxCol() + 1; i++) {
        res.push(this.formatCellValue(rowIntance.getCell(i)));
      }
      return res;
    }
    if(val.type === 'colPosition') {
      let res: TAllTypes[] = [];
      for(let i = 0; i < this.tableDatas.getMaxRow() + 1;i++) {
        let rowIntance = this.tableDatas.getRow(i);
        for(let j = 0; j < rowIntance.getMaxCol() + 1; j++) {
          let cell = rowIntance.getCell(j);
          res.push(this.formatCellValue(cell));
        }
      }
    }
  }
  protected formatCellValue(cell: Cell|null): TAllTypes {
    if(cell && cell.value.getActualValue().type !== 'empty' && cell.value.getActualValue().type !== 'ERROR') {
      let value = cell.value.getActualValue().getValue();
      if(typeof value === 'boolean') {
        return {
          type: 'value',
          dataType: 'boolean',
          value: value
        }
      }
      if(typeof value === 'string' && isNaN(Number(value))) {
        return {
          type: 'value',
          dataType: 'string',
          value: value
        }
      }
      if((typeof value === 'string' || typeof value === 'number') && !isNaN(Number(value))) {
        return {
          type: 'value',
          dataType: 'number',
          value: Number(value)
        }
      }
    } else {
      return null;
    }
  }
}